package com.lx.apk.encrypt.utils;

import java.io.File;
import java.io.FilenameFilter;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 *
 * date 2020/8/6.
 * description： 加密工具类
 */
public class EncryptUtils {
    private final byte[] KEY = "QUmkLrrISiud6RPU".getBytes(); // 加密使用的key
    private final byte[] IV = "eh7aJlOdHCNsGNcD".getBytes(); // 偏移值
    private final String ALGORITHM = "AES/CBC/PKCS5Padding"; // 加密算法
    private Cipher encryptCipher; // 加密
    private Cipher decryptCipher; // 解密

    /**
     * 使用单例
     */
    private EncryptUtils() {
        try {
            // 初始化加密算法
            decryptCipher = Cipher.getInstance(ALGORITHM);
            encryptCipher = Cipher.getInstance(ALGORITHM);
            SecretKeySpec key = new SecretKeySpec(KEY, "AES");
            encryptCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));
            decryptCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class SingletonHolder {
        private static final EncryptUtils INSTANCE = new EncryptUtils();
    }

    public static EncryptUtils getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 加密apk
     *
     * @param srcApkFile 源apk文件的地址
     * @param dstApkFile 新apk文件的地址
     */
    public void encryptApkFile(File srcApkFile, File dstApkFile) {
        if (srcApkFile == null || !srcApkFile.exists()) {
            LogUtils.e("source apk file not exist");
            return;
        }
        // 解压apk到指定文件夹
        ZipUtils.unZip(srcApkFile, dstApkFile);

        // 获取所有的dex（可能存在分包的情况，即有多个dex文件）
        File[] dexFiles = dstApkFile.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File file, String s) {
                // 提取所有的.dex文件
                return s.endsWith(".dex");
            }
        });

        if (dexFiles == null || dexFiles.length <= 0) {
            LogUtils.i("this apk is invalidate");
            return;
        }

        for (File dexFile : dexFiles) {
            // 读取dex中的数据
            byte[] buffer = FileUtils.getBytes(dexFile);
            if (buffer != null) {
                // 加密
                byte[] encryptBytes = encrypt(buffer);
                if (encryptBytes != null) {
                    //修改.dex名为_.dex,避免等会与aar中的.dex重名
                    int indexOf = dexFile.getName().indexOf(".dex");
                    String newName = dexFile.getParent() + File.separator +
                            dexFile.getName().substring(0, indexOf) + "_.dex";
                    // 写数据， 替换原来的数据
                    FileUtils.wirte(new File(newName), encryptBytes);
                    dexFile.delete();
                } else {
                    LogUtils.e("Failed to encrypt dex data");
                    return;
                }
            } else {
                LogUtils.e("Failed to read dex data");
                return;
            }
        }
    }

    /**
     * 加密
     *
     * @param data
     * @return
     */
    private byte[] encrypt(byte[] data) {
        try {
            return encryptCipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密
     *
     * @param data
     * @return
     */
    private byte[] decrypt(byte[] data) {
        try {
            return decryptCipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
